using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using GameData;

namespace SpaceShooter
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Vector2 SCREEN_SIZE = new Vector2(800.0f, 600.0f);
        Level[] levels = null;
        int currentLevel = 0;
        int lives;
        int health;
        double deathTimer = 0.0;
        bool GameOverScreen = false;
        Texture2D gameOverBackground;
        GameOverScreen gameOverScreen;
        

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            IsFixedTimeStep = false;
            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;
            graphics.ApplyChanges();
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            levels = new Level[3];
            // Create the levels, load from files, etc
            Texture2D playerTex = Content.Load<Texture2D>("sprites\\gradius");
            Texture2D bgTex = Content.Load<Texture2D>("sprites\\bg");
            Texture2D bulletTex = Content.Load<Texture2D>("sprites\\bullet");
            Texture2D bossTex;

            gameOverScreen = new GameOverScreen(Content.Load<Texture2D>("sprites\\bg"), 
                new Vector2(800.0f, 600.0f), Content);


            Enemy[] enemyList;
            Powerup[] powerupList;
            double[] timePowerupList;
            double[] timeList;
            LevelData[] levelDat;
            LevelPowerupData[] levelPowerDat;
            for( int i=0; i<3; i++ )
            {

                levelDat = Content.Load<LevelData[]>("levels\\Level" + Convert.ToString(i+1));// + (i+1));
                levelPowerDat = Content.Load<LevelPowerupData[]>("levels\\LevelP" + Convert.ToString(i + 1));

                bossTex = Content.Load<Texture2D>("sprites\\boss" + i);
                levelDat = Content.Load<LevelData[]>("levels\\Level1");// + (i+1));

                enemyList = new Enemy[levelDat.Length];
                timeList = new double[levelDat.Length];
                powerupList = new Powerup[levelPowerDat.Length];
                timePowerupList = new double[levelPowerDat.Length];
                for (int j = 0; j < levelDat.Length; j++)
                {
                    Texture2D enemyTex = Content.Load<Texture2D>("sprites\\" + levelDat[j].type);
                    Vector2 startPos = new Vector2((float)levelDat[j].xpos, (float)levelDat[j].ypos);
                    enemyList[j] = new Enemy(enemyTex, SCREEN_SIZE, startPos, levelDat[j].health, levelDat[j].path);
                    enemyList[j].angle = Math.PI;
                    timeList[j] = levelDat[j].time;
                }

                for (int j = 0; j < levelPowerDat.Length; j++)
                {
                    Texture2D powerupTex = Content.Load<Texture2D>("sprites\\" + levelPowerDat[j].name);
                    Vector2 startpos = new Vector2((float)levelPowerDat[j].xpos, (float)levelPowerDat[j].ypos);
                    powerupList[j] = new Powerup(powerupTex, SCREEN_SIZE, levelPowerDat[j].time, levelPowerDat[j].type, startpos);
                    timePowerupList[j] = levelPowerDat[j].time;
                }
                Texture2D[] t_arr = new Texture2D[5];
                t_arr[0] = Content.Load<Texture2D>("sprites\\health_bar");
                t_arr[1] = Content.Load<Texture2D>("sprites\\heart");
                levels[i] = new Level(SCREEN_SIZE, bgTex, playerTex, bulletTex, bossTex, powerupList, t_arr, i, enemyList, timeList, timePowerupList);
            }
            // Menu/Start first level
            levels[0].start();
        }

        protected override void UnloadContent(){ }

        protected override void Update(GameTime gameTime)
        {
            KeyboardState ks = Keyboard.GetState();
            double elapsedTime = gameTime.ElapsedGameTime.TotalSeconds;
            PlayerShip ps;
            if (ks.IsKeyDown(Keys.Escape))
                this.Exit();
            if (gameOverScreen.getRestart())
            {
                currentLevel = 0;
                ps = levels[currentLevel].ps;
                ps.health = 3;
                ps.lives = 3;
                lives = 3;
                health = 3;
                //TimeSpan ts = gameTime.ElapsedGameTime;
                //gameTime.ElapsedGameTime.Subtract(ts);
                GameOverScreen = false;
                ps.alive = true;
                gameOverScreen.restart = false;
                for (int i = 0; i < levels.Length; i++)
                    levels[i].reset();
                levels[currentLevel].start();
            }
            else
                ps = levels[currentLevel].ps;
                

            if (ps.alive)
            {
                if (ks.IsKeyDown(Keys.Up))
                {
                    ps.vel.Y -= 35.0f;
                }
                if (ks.IsKeyDown(Keys.Down))
                {
                    ps.vel.Y += 35.0f;
                }
                if (ks.IsKeyDown(Keys.Left))
                {
                    ps.state = ShipState.DECCELERATE;
                    ps.frameCount = ps.frameCount % ps.animateSequence[(int)ps.state].Length;
                    ps.vel.X -= 35.0f;
                }
                if (ks.IsKeyDown(Keys.Right))
                {
                    ps.state = ShipState.ACCELERATE;
                    ps.frameCount = ps.frameCount % ps.animateSequence[(int)ps.state].Length;
                    ps.vel.X += 35.0f;
                }
                if (ks.IsKeyDown(Keys.Z) && ps.fireTimer <= 0)
                {
                    levels[currentLevel].shoot();
                }
                if (ks.IsKeyDown(Keys.Q))
                {
                    if (ps.primaryWeapon == 0)
                        ps.primaryWeapon = 1;
                    else
                        ps.primaryWeapon = 0;
                }
                if (ks.IsKeyDown(Keys.A))
                {
                    ps.weaponType = (ps.weaponType + 1) % 2;
                }
                if (ks.IsKeyUp(Keys.Up) && ks.IsKeyUp(Keys.Down) && ks.IsKeyUp(Keys.Left) && ks.IsKeyUp(Keys.Right))
                {
                    if (ps.state != ShipState.NEUTRAL && ps.state != ShipState.EXPLODE)
                    {
                        ps.state = ShipState.NEUTRAL;
                        ps.frameCount = ps.frameCount % ps.animateSequence[(int)ps.state].Length;
                    }
                }
            }

            int status = levels[currentLevel].update(elapsedTime);
            if (status == 1)
            {
                levels[currentLevel].stop();
                currentLevel++;
                if (currentLevel < 3)
                {
                    levels[currentLevel].ps.lives = lives;
                    levels[currentLevel].ps.health = health;
                    levels[currentLevel].ps.state = ShipState.NEUTRAL;
                    levels[currentLevel].ps.frameCount = 0;
                    levels[currentLevel].ps.frameTimer = 0;
                    levels[currentLevel].start();
                }
            }
            base.Update(gameTime);

            if (!ps.alive && deathTimer <= 0)
            {
                //lives--;
                ps.health--;
                health = ps.health;
                if (ps.health == 0)
                {
                    ps.lives--;
                    lives = ps.lives;
                    ps.health = 3;
                    health = ps.health;
                }
                deathTimer = 3.0;
                Console.WriteLine("Lives Left: " + ps.lives);
                //game over
                if (ps.lives < 0)
                {
                    levels[currentLevel].isGameOver = true;
                    levels[currentLevel].stop();
                    GameOverScreen = true;
                }
            }
            if (deathTimer > 0)
            {
                ps.state = ShipState.EXPLODE;
                deathTimer -= elapsedTime;
            }
            if (deathTimer <= 0 && !ps.alive)
            {
                ps.alive = true;
                ps.state = ShipState.NEUTRAL;
            }
            if (GameOverScreen)
            {
                ps.alive = false;
                gameOverScreen.update();
            }


        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
            if (!GameOverScreen && currentLevel < levels.Length)
            if (!GameOverScreen && currentLevel<3 )

                levels[currentLevel].draw(spriteBatch);
            else
            {
                gameOverScreen.draw(spriteBatch);
                //these won't fully draw?
                spriteBatch.DrawString(Content.Load<SpriteFont>("levels\\Arial"), "Game Over",
                    new Vector2(800 / 2 - 100, 600 / 2 - 100), Color.White);
                spriteBatch.DrawString(Content.Load<SpriteFont>("levels\\Arial"), "Press 'R' to restart, or ESC to quit",
                    new Vector2(40, 800 / 2), Color.White);

            }
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}
